#include <Qsci/qsciscintilla.h>
#include <Qsci/qscilexer.h>
#include <QFontDialog>
#include <QMessageBox>
#include "Include/Settings.h"
#include "Appearance.h"
#include "ui_Appearance.h"
#include "Include/Plugins.h"
#include "Include/IEditors.h"
#include "Include/IEditor.h"
#include "Include/ITheme.h"
#include "Include/ILexers.h"
#include "ThemeEditor.h"
#include "SelectThemeName.h"

Appearance::Appearance(QWidget *parent) :
    ISettingsView(parent),
    ui(new Ui::Appearance)
{
    ui->setupUi(this);

    _curentFont = Plugins::Settings::instance()->font();
    _curentMonoFont = Plugins::Settings::instance()->monoFont();
    connect(ui->selFont, SIGNAL(clicked()), SLOT(onSelFont()));
    connect(ui->selectMonoBtn, SIGNAL(clicked()), SLOT(onSelMonoFont()));
    connect(ui->stylesList, SIGNAL(currentRowChanged(int)), SLOT(onThemeChanged(int)));
    connect(ui->lexersCmb, SIGNAL(currentIndexChanged(QString)), SLOT(onLexerChanged(QString)));
    connect(ui->editStyleBtn, SIGNAL(clicked()), SLOT(onThemeEdit()));
    connect(ui->addStyleBtn, SIGNAL(clicked()), SLOT(onThemeAdd()));
    connect(ui->deleteStyleBtn, SIGNAL(clicked()), SLOT(onThemeDelete()));

    ui->fontPreview->setReadOnly(true);
    ui->monoPreview->setReadOnly(true);

    ui->editStyleBtn->setEnabled(false);
    ui->deleteStyleBtn->setEnabled(false);


    rebuildStylesList(Plugins::Settings::instance()->currentThemeName());

    PluginWrapper<Lexers::ILexers> lexers = loadPlugin<Lexers::ILexers>("liblexers.so");
    ui->lexersCmb->addItems(lexers->names());

    foreach(QString lexName, lexers->names()){
        PluginWrapper<Plugins::IEditors> editors = loadPlugin<Plugins::IEditors>("libtexteditor.so");
        Plugins::IEditor *ed = editors->createEditor(Plugins::IEditors::Text, this);
        ed->setStatusBarVisible(false);
        QWidget * w = ed->widget();
        w->setProperty("name", lexName);
        ui->preview->addWidget(w);
        ed->setLexerByName(lexName);
        if (lexName == "Default"){
            ed->setText(
                "Default lexer\n"
                "   Example of text\n"
                "   Example \"of text\"\n"
            );

        } else if (lexName == "Python"){
            ed->setText(
                "from PyQt4 import QtGui\n"
                "class SettingsView(QtGui.QDialog):\n"
                "   def __init__(self, parent = None):\n"
                "       super(QtGui.QDialog,  self).__init__(parent)\n"
                "       #comment\n"
                "       s = \"string\"\n"
                "       i = 15\n"
                "       self.createViews()\n"
                "   @decorator\n"
                "   def createViews(self):\n"
                "       pass\n"
            );
        } else if (lexName == "jinja2 + html"){
            ed->setText(
                "#include 'header.tmpl'\n"
                "#import 'some.tmpl' as macroses\n"
                "\n"
                "Text <b>{{ ticket.mode.translated() }}</b><br />\n"
                "#if condition:\n"
                "    Condition text: <b>{{text}}</b><br/>\n"
                "#endif\n"
                "<br />"
            );
        }

        //ui->preview->setReadOnly(true);
    }

    updateVisualTheme();
    onLexerChanged(lexers->names()[0]);
    updateFont();
    updateMonoFont();
}

Appearance::~Appearance()
{
    delete ui;
}

QString Appearance::displayName()
{
    return trUtf8("Appearance");
}

QIcon Appearance::icon()
{
    return QIcon::fromTheme("preferences-desktop-theme");
}

void Appearance::onSelFont()
{
    QFontDialog d(_curentFont, this);
    if (d.exec() == QDialog::Accepted){
        _curentFont = d.selectedFont();
        updateFont();
    }
}

void Appearance::onSelMonoFont()
{
    QFontDialog d(_curentMonoFont, this);
    if (d.exec() == QDialog::Accepted){
        _curentMonoFont = d.selectedFont();
        updateMonoFont();
    }
}

void Appearance::updateFont()
{
    ui->fontPreview->setFont(_curentFont);
    //ui->preview->lexer()->setFont(_curentFont);
    QFontInfo info = QFontInfo(_curentFont);
    ui->fontPreview->setText(QString("%1 %2").arg(info.family()).arg(info.pointSize()));
    updateVisualTheme();
}

void Appearance::updateMonoFont()
{
    ui->monoPreview->setFont(_curentMonoFont);
    QFontInfo info = QFontInfo(_curentMonoFont);
    ui->monoPreview->setText(QString("%1 %2").arg(info.family()).arg(info.pointSize()));
}

void Appearance::onLexerChanged(const QString& name)
{
    for(int i = 0; i < ui->preview->count(); i++){
        if (name == ui->preview->widget(i)->property("name").toString()){
            ui->preview->setCurrentIndex(i);
            break;
        }
    }
}

void Appearance::updateVisualTheme()
{
    ITheme *theme = NULL;
    if (ui->stylesList->currentItem())
        theme = Plugins::Settings::instance()->themeByName(ui->stylesList->currentItem()->text());

    for(int i = 0; i < ui->preview->count(); i++){
        Plugins::IEditor *ed = qobject_cast<Plugins::IEditor *>(ui->preview->widget(i));
        if (ed)
            ed->setTheme(theme, &_curentFont);
    }
}

void Appearance::onThemeEdit()
{
    QString themeName = "unknown";
    if (ui->stylesList->currentItem())
        themeName = ui->stylesList->currentItem()->text();
    ITheme *theme = Plugins::Settings::instance()->themeByName(themeName);
    ThemeEditor edt(theme, this);
    if (edt.exec() == QDialog::Accepted && !_themesToSave.contains(themeName))
        _themesToSave.append(themeName);
}

void Appearance::save()
{
    foreach(QString themeName, _themesToSave){
        Plugins::Settings::instance()->themeByName(themeName)->save();
    }

    if (_themesToSave.length())
        Plugins::Settings::instance()->setThemeChanged();

    Plugins::Settings::instance()->setFont(_curentFont);
    Plugins::Settings::instance()->setMonoFont(_curentMonoFont);
    _themesToSave.clear();
    if (ui->stylesList->currentItem())
        Plugins::Settings::instance()->setCurrentThemeName(ui->stylesList->currentItem()->text());
}

void Appearance::onThemeChanged(int row)
{
    ui->editStyleBtn->setEnabled(row >= 0);
    ui->deleteStyleBtn->setEnabled(row >= 0);
    if (row >= 0){
        updateVisualTheme();
    }
}

void Appearance::onThemeAdd()
{
    SelectThemeName dlg(this);
    if (dlg.exec() != QDialog::Accepted)
        return;
    QString name = dlg.name();
    QFile f(Plugins::Settings::instance()->themesPath()+"/"+name+".conf");
    f.open(QIODevice::WriteOnly);
    f.close();

    rebuildStylesList(name);
}

void Appearance::onThemeDelete()
{
    if (QMessageBox::question(this, tr("Delete"), tr("Really want to delete this theme?"), QMessageBox::Yes | QMessageBox::No)){
        QFile::remove(Plugins::Settings::instance()->themesPath()+"/"+ui->stylesList->currentItem()->text()+".conf");
        rebuildStylesList();
    }
}

void Appearance::rebuildStylesList(const QString & name)
{
    ui->stylesList->clear();
    foreach(QString themeName, Plugins::Settings::instance()->themesList()){
        ui->stylesList->addItem(themeName);
    }
    if (!name.isEmpty()){
        QList<QListWidgetItem *> found = ui->stylesList->findItems(name, Qt::MatchExactly);
        if (found.length() > 0)
            ui->stylesList->setCurrentItem(found[0]);
        else
            ui->stylesList->setCurrentRow(0);
    } else {
        ui->stylesList->setCurrentRow(0);
    }
}
